/*
 Copyright 2011 and onwards Joao C. R. Pereira

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
      limitations under the License.
*/

#include <string.h>
#include "Buffer.h"
#include "Memory.h"

Buffer Buffer_New(size_t capacity, size_t factor) {
  
  Buffer buffer = NewObj(BufferObj);

  Buffer_Init(buffer, capacity, factor);
  return buffer;
}

void Buffer_Init(StaticBuffer * buffer, size_t capacity, size_t factor) {

  STARTSAFEPOINT(buffer);

  buffer->len = 0;
  buffer->capacity = capacity;
  buffer->factor = factor;
  buffer->bytes = (byte*)malloc(capacity);
  memset(buffer->bytes, 0, buffer->capacity);

  CHECKSAFEPOINTS(buffer);
}

size_t Buffer_GetCapacity(Buffer buffer) {

  CHECKSAFEPOINTS(buffer);
  return buffer->capacity;
}

size_t Buffer_GetLength(Buffer buffer) {

  CHECKSAFEPOINTS(buffer);
  return buffer->len;
}

void Buffer_AddByte(Buffer buffer, byte b) {

  CHECKSAFEPOINTS(buffer);

  if (buffer->len < (buffer->capacity)) {

    buffer->bytes[buffer->len] = b;
    buffer->len++;

  } else {
    Assert_IsTrue(buffer->factor > 0);
    buffer->capacity += buffer->factor;
    buffer->bytes = (byte*)realloc(buffer->bytes, buffer->capacity);
    buffer->bytes[buffer->len] = b;
    buffer->len++;

  }
  CHECKSAFEPOINTS(buffer);
}

void Buffer_AddWord(Buffer buffer, word w) {

  byte a,b;

  Assert_IsTrue(w <= MAXWORD);
  a = w / 256;
  b = w - (a*256);
  Buffer_AddByte(buffer, a);
  Buffer_AddByte(buffer, b);
}

void Buffer_Clear(Buffer buffer) {

  CHECKSAFEPOINTS(buffer);
  buffer->len = 0;
  memset(buffer->bytes, 0, buffer->capacity);
}

void Buffer_Print(Buffer buffer) {

  uint i;

  CHECKSAFEPOINTS(buffer);

  for(i=0;i<buffer->len;i++) {	
    printf("%hhu ", buffer->bytes[i]);
  }
}

void Buffer_EnsureCapacity(Buffer buffer, size_t capacity) {
  
  CHECKSAFEPOINTS(buffer);  
  
  if (buffer->capacity < capacity) {
 
    buffer->capacity = capacity + buffer->factor;
    buffer->bytes = (byte*)realloc(buffer->bytes, buffer->capacity);
   
  }
  CHECKSAFEPOINTS(buffer);  
}

